<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<meta name="generator" content="pdoc 0.9.2" />
<title>graia.application.message.parser.literature API documentation</title>
<meta name="description" content="" />
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/sanitize.min.css" integrity="sha256-PK9q560IAAa6WVRRh76LtCaI8pjTJ2z11v0miyNNjrs=" crossorigin>
<link rel="preload stylesheet" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/11.0.1/typography.min.css" integrity="sha256-7l/o7C8jubJiy74VsKTidCy1yBkRtiUGbVkYBylBqUg=" crossorigin>
<link rel="stylesheet preload" as="style" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/styles/github.min.css" crossorigin>
<style>:root{--highlight-color:#fe9}.flex{display:flex !important}body{line-height:1.5em}#content{padding:20px}#sidebar{padding:30px;overflow:hidden}#sidebar > *:last-child{margin-bottom:2cm}.http-server-breadcrumbs{font-size:130%;margin:0 0 15px 0}#footer{font-size:.75em;padding:5px 30px;border-top:1px solid #ddd;text-align:right}#footer p{margin:0 0 0 1em;display:inline-block}#footer p:last-child{margin-right:30px}h1,h2,h3,h4,h5{font-weight:300}h1{font-size:2.5em;line-height:1.1em}h2{font-size:1.75em;margin:1em 0 .50em 0}h3{font-size:1.4em;margin:25px 0 10px 0}h4{margin:0;font-size:105%}h1:target,h2:target,h3:target,h4:target,h5:target,h6:target{background:var(--highlight-color);padding:.2em 0}a{color:#058;text-decoration:none;transition:color .3s ease-in-out}a:hover{color:#e82}.title code{font-weight:bold}h2[id^="header-"]{margin-top:2em}.ident{color:#900}pre code{background:#f8f8f8;font-size:.8em;line-height:1.4em}code{background:#f2f2f1;padding:1px 4px;overflow-wrap:break-word}h1 code{background:transparent}pre{background:#f8f8f8;border:0;border-top:1px solid #ccc;border-bottom:1px solid #ccc;margin:1em 0;padding:1ex}#http-server-module-list{display:flex;flex-flow:column}#http-server-module-list div{display:flex}#http-server-module-list dt{min-width:10%}#http-server-module-list p{margin-top:0}.toc ul,#index{list-style-type:none;margin:0;padding:0}#index code{background:transparent}#index h3{border-bottom:1px solid #ddd}#index ul{padding:0}#index h4{margin-top:.6em;font-weight:bold}@media (min-width:200ex){#index .two-column{column-count:2}}@media (min-width:300ex){#index .two-column{column-count:3}}dl{margin-bottom:2em}dl dl:last-child{margin-bottom:4em}dd{margin:0 0 1em 3em}#header-classes + dl > dd{margin-bottom:3em}dd dd{margin-left:2em}dd p{margin:10px 0}.name{background:#eee;font-weight:bold;font-size:.85em;padding:5px 10px;display:inline-block;min-width:40%}.name:hover{background:#e0e0e0}dt:target .name{background:var(--highlight-color)}.name > span:first-child{white-space:nowrap}.name.class > span:nth-child(2){margin-left:.4em}.inherited{color:#999;border-left:5px solid #eee;padding-left:1em}.inheritance em{font-style:normal;font-weight:bold}.desc h2{font-weight:400;font-size:1.25em}.desc h3{font-size:1em}.desc dt code{background:inherit}.source summary,.git-link-div{color:#666;text-align:right;font-weight:400;font-size:.8em;text-transform:uppercase}.source summary > *{white-space:nowrap;cursor:pointer}.git-link{color:inherit;margin-left:1em}.source pre{max-height:500px;overflow:auto;margin:0}.source pre code{font-size:12px;overflow:visible}.hlist{list-style:none}.hlist li{display:inline}.hlist li:after{content:',\2002'}.hlist li:last-child:after{content:none}.hlist .hlist{display:inline;padding-left:1em}img{max-width:100%}td{padding:0 .5em}.admonition{padding:.1em .5em;margin-bottom:1em}.admonition-title{font-weight:bold}.admonition.note,.admonition.info,.admonition.important{background:#aef}.admonition.todo,.admonition.versionadded,.admonition.tip,.admonition.hint{background:#dfd}.admonition.warning,.admonition.versionchanged,.admonition.deprecated{background:#fd4}.admonition.error,.admonition.danger,.admonition.caution{background:lightpink}</style>
<style media="screen and (min-width: 700px)">@media screen and (min-width:700px){#sidebar{width:30%;height:100vh;overflow:auto;position:sticky;top:0}#content{width:70%;max-width:100ch;padding:3em 4em;border-left:1px solid #ddd}pre code{font-size:1em}.item .name{font-size:1em}main{display:flex;flex-direction:row-reverse;justify-content:flex-end}.toc ul ul,#index ul{padding-left:1.5em}.toc > ul > li{margin-top:.5em}}</style>
<style media="print">@media print{#sidebar h1{page-break-before:always}.source{display:none}}@media print{*{background:transparent !important;color:#000 !important;box-shadow:none !important;text-shadow:none !important}a[href]:after{content:" (" attr(href) ")";font-size:90%}a[href][title]:after{content:none}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h1,h2,h3,h4,h5,h6{page-break-after:avoid}}</style>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.1/highlight.min.js" integrity="sha256-Uv3H6lx7dJmRfRvH8TH6kJD1TSK1aFcwgx+mdg3epi8=" crossorigin></script>
<script>window.addEventListener('DOMContentLoaded', () => hljs.initHighlighting())</script>
</head>
<body>
<main>
<article id="content">
<header>
<h1 class="title">Module <code>graia.application.message.parser.literature</code></h1>
</header>
<section id="section-intro">
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">import re
import shlex
import getopt
import itertools
from typing import Dict, List, Tuple
from graia.broadcast.entities.dispatcher import BaseDispatcher
from graia.broadcast.entities.signatures import Force
from graia.broadcast.exceptions import ExecutionStop

from graia.broadcast.interfaces.dispatcher import DispatcherInterface
from graia.broadcast.utilles import printer
from graia.application.message.chain import MessageChain, MessageIndex
from graia.application.message.elements import Element
from graia.application.message.elements.internal import (
    At,
    App,
    Json,
    Plain,
    Quote,
    Source,
    Xml,
    Voice,
    Poke,
    FlashImage,
)

from graia.application.message.parser.pattern import (
    BoxParameter,
    ParamPattern,
    SwitchParameter,
)

BLOCKING_ELEMENTS = (Xml, Json, App, Poke, Voice, FlashImage)


class Literature(BaseDispatcher):
    &#34;旅途的浪漫&#34;

    always = False
    prefixs: Tuple[str]  # 匹配前缀
    arguments: Dict[str, ParamPattern]

    allow_quote: bool
    skip_one_at_in_quote: bool

    def __init__(
        self,
        *prefixs,
        arguments: Dict[str, ParamPattern] = None,
        allow_quote: bool = False,
        skip_one_at_in_quote: bool = False,
    ) -&gt; None:
        self.prefixs = prefixs
        self.arguments = arguments or {}
        self.allow_quote = allow_quote
        self.skip_one_at_in_quote = skip_one_at_in_quote

    def trans_to_map(self, message_chain: MessageChain):
        string_result: List[str] = []
        id_elem_map: Dict[int, Element] = {}

        for elem in message_chain.__root__:
            if isinstance(elem, Plain):
                string_result.append(
                    re.sub(
                        r&#34;\$(?P&lt;id&gt;\d+)&#34;,
                        lambda match: f&#39;\\${match.group(&#34;id&#34;)}&#39;,
                        elem.text,
                    )
                )
            else:
                index = len(id_elem_map) + 1
                string_result.append(f&#34;${index}&#34;)
                id_elem_map[index] = elem

        return (&#34;&#34;.join(string_result), id_elem_map)

    def gen_long_map(self):
        result = {}
        for param_name, arg in self.arguments.items():
            for long in arg.longs:
                if long in result:
                    raise ValueError(&#34;conflict item&#34;)
                result[long] = param_name
        return result

    def gen_short_map(self):
        result = {}
        for param_name, arg in self.arguments.items():
            if arg.short in result:
                raise ValueError(&#34;conflict item&#34;)
            result[arg.short] = param_name
        return result

    def gen_long_map_with_bar(self):
        return {(&#34;--&#34; + k): v for k, v in self.gen_long_map().items()}

    def gen_short_map_with_bar(self):
        return {(&#34;-&#34; + k): v for k, v in self.gen_short_map().items() if k is not None}

    def parse_message(self, message_chain: MessageChain):
        string_result, id_elem_map = self.trans_to_map(message_chain)

        parsed_args, variables = getopt.getopt(
            shlex.split(string_result),
            &#34;&#34;.join(
                [
                    arg.short if isinstance(arg, SwitchParameter) else (arg.short + &#34;:&#34;)
                    for arg in self.arguments.values()
                    if arg.short
                ]
            ),
            [
                long if isinstance(arg, SwitchParameter) else long + &#34;=&#34;
                for arg in self.arguments.values()
                for long in arg.longs
            ],
        )
        map_with_bar = {**self.gen_long_map_with_bar(), **self.gen_short_map_with_bar()}
        parsed_args = {
            map_with_bar[k]: (
                MessageChain.create(
                    [
                        Plain(i)
                        if not re.match(&#34;^\$\d+$&#34;, i)
                        else id_elem_map[int(i[1:])]
                        for i in re.split(r&#34;((?&lt;!\\)\$[0-9]+)&#34;, v)
                        if i
                    ]
                ).asMerged()
                if isinstance(self.arguments[map_with_bar[k]], BoxParameter)
                else (
                    self.arguments[map_with_bar[k]].auto_reverse
                    and not self.arguments[map_with_bar[k]].default
                    or True
                ),
                self.arguments[map_with_bar[k]],
            )
            for k, v in parsed_args
        }
        variables = [
            MessageChain.create(
                [
                    Plain(i) if not re.match(&#34;^\$\d+$&#34;, i) else id_elem_map[int(i[1:])]
                    for i in re.split(r&#34;((?&lt;!\\)\$[0-9]+)&#34;, v)
                    if i
                ]
            ).asMerged()
            for v in variables
        ]
        for param_name, argument_setting in self.arguments.items():
            if param_name not in parsed_args:
                if argument_setting.default is not None:
                    parsed_args[param_name] = (
                        argument_setting.default,
                        argument_setting,
                    )
                else:
                    raise ExecutionStop()

        return (parsed_args, variables)

    def prefix_match(self, target_chain: MessageChain):
        target_chain = target_chain.asMerged()

        chain_frames: List[MessageChain] = target_chain.split(&#34; &#34;, raw_string=True)

        # 前缀匹配
        if len(self.prefixs) &gt; len(chain_frames):
            return
        for index, current_prefix in enumerate(self.prefixs):
            current_frame = chain_frames[index]
            if (
                not current_frame.__root__
                or type(current_frame.__root__[0]) is not Plain
            ):
                return
            if current_frame.__root__[0].text != current_prefix:
                return

        chain_frames = chain_frames[len(self.prefixs) :]
        return MessageChain.create(
            list(itertools.chain(*[i.__root__ + [Plain(&#34; &#34;)] for i in chain_frames]))[
                :-1
            ]
        ).asMerged()

    async def beforeDispatch(self, interface: DispatcherInterface):
        message_chain: MessageChain = (
            await interface.lookup_param(
                &#34;__literature_messagechain__&#34;, MessageChain, None
            )
        ).exclude(Source)
        if set([i.__class__ for i in message_chain.__root__]).intersection(
            BLOCKING_ELEMENTS
        ):
            raise ExecutionStop()
        if self.allow_quote and message_chain.has(Quote):
            # 自动忽略自 Quote 后第一个 At
            message_chain = message_chain[(1, None):]
            if self.skip_one_at_in_quote and message_chain.__root__:
                if message_chain.__root__[0].__class__ is At:
                    message_chain = message_chain[(1, 1):]
        noprefix = self.prefix_match(message_chain)
        if noprefix is None:
            raise ExecutionStop()

        interface.execution_contexts[-1].literature_detect_result = self.parse_message(
            noprefix
        )

    async def catch(self, interface: DispatcherInterface):
        if interface.name == &#34;__literature_messagechain__&#34;:
            return

        result = interface.execution_contexts[-1].literature_detect_result
        if result:
            match_result, variargs = result
            if interface.default == &#34;__literature_variables__&#34;:
                return variargs

            arg_fetch_result = match_result.get(interface.name)
            if arg_fetch_result:

                match_value, raw_argument = arg_fetch_result
                if isinstance(raw_argument, SwitchParameter):
                    return Force(match_value)
                elif interface.annotation is ParamPattern:
                    return raw_argument
                elif match_value is not None:
                    return match_value


if __name__ == &#34;__main__&#34;:
    from graia.application.message.elements.internal import AtAll, At

    mc = MessageChain.create(
        [
            Plain(&#39;test n --f3 &#34;1 2 tsthd thsd ydj re7u  &#39;),
            At(351453455),
            Plain(&#39; &#34; --f34 &#34;arg arega er ae aghr ae rtyh&#39;),
            # At(656735757),
            Plain(&#39; &#34;&#39;),
        ]
    )

    l = Literature(
        &#34;test&#34;,
        &#34;n&#34;,
        arguments={
            &#34;a&#34;: BoxParameter([&#34;test_f1&#34;, &#34;f23&#34;], &#34;f&#34;),
            &#34;b&#34;: SwitchParameter([&#34;f34&#34;], &#34;d&#34;),
        },
    )
    from devtools import debug

    # debug(l.prefix_match(mc))
    debug(l.parse_message(l.prefix_match(mc)))
    print(mc.asDisplay())</code></pre>
</details>
</section>
<section>
</section>
<section>
</section>
<section>
</section>
<section>
<h2 class="section-title" id="header-classes">Classes</h2>
<dl>
<dt id="graia.application.message.parser.literature.Literature"><code class="flex name class">
<span>class <span class="ident">Literature</span></span>
<span>(</span><span>*prefixs, arguments: Dict[str, <a title="graia.application.message.parser.pattern.ParamPattern" href="pattern.html#graia.application.message.parser.pattern.ParamPattern">ParamPattern</a>] = None, allow_quote: bool = False, skip_one_at_in_quote: bool = False)</span>
</code></dt>
<dd>
<div class="desc"><p>旅途的浪漫</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">class Literature(BaseDispatcher):
    &#34;旅途的浪漫&#34;

    always = False
    prefixs: Tuple[str]  # 匹配前缀
    arguments: Dict[str, ParamPattern]

    allow_quote: bool
    skip_one_at_in_quote: bool

    def __init__(
        self,
        *prefixs,
        arguments: Dict[str, ParamPattern] = None,
        allow_quote: bool = False,
        skip_one_at_in_quote: bool = False,
    ) -&gt; None:
        self.prefixs = prefixs
        self.arguments = arguments or {}
        self.allow_quote = allow_quote
        self.skip_one_at_in_quote = skip_one_at_in_quote

    def trans_to_map(self, message_chain: MessageChain):
        string_result: List[str] = []
        id_elem_map: Dict[int, Element] = {}

        for elem in message_chain.__root__:
            if isinstance(elem, Plain):
                string_result.append(
                    re.sub(
                        r&#34;\$(?P&lt;id&gt;\d+)&#34;,
                        lambda match: f&#39;\\${match.group(&#34;id&#34;)}&#39;,
                        elem.text,
                    )
                )
            else:
                index = len(id_elem_map) + 1
                string_result.append(f&#34;${index}&#34;)
                id_elem_map[index] = elem

        return (&#34;&#34;.join(string_result), id_elem_map)

    def gen_long_map(self):
        result = {}
        for param_name, arg in self.arguments.items():
            for long in arg.longs:
                if long in result:
                    raise ValueError(&#34;conflict item&#34;)
                result[long] = param_name
        return result

    def gen_short_map(self):
        result = {}
        for param_name, arg in self.arguments.items():
            if arg.short in result:
                raise ValueError(&#34;conflict item&#34;)
            result[arg.short] = param_name
        return result

    def gen_long_map_with_bar(self):
        return {(&#34;--&#34; + k): v for k, v in self.gen_long_map().items()}

    def gen_short_map_with_bar(self):
        return {(&#34;-&#34; + k): v for k, v in self.gen_short_map().items() if k is not None}

    def parse_message(self, message_chain: MessageChain):
        string_result, id_elem_map = self.trans_to_map(message_chain)

        parsed_args, variables = getopt.getopt(
            shlex.split(string_result),
            &#34;&#34;.join(
                [
                    arg.short if isinstance(arg, SwitchParameter) else (arg.short + &#34;:&#34;)
                    for arg in self.arguments.values()
                    if arg.short
                ]
            ),
            [
                long if isinstance(arg, SwitchParameter) else long + &#34;=&#34;
                for arg in self.arguments.values()
                for long in arg.longs
            ],
        )
        map_with_bar = {**self.gen_long_map_with_bar(), **self.gen_short_map_with_bar()}
        parsed_args = {
            map_with_bar[k]: (
                MessageChain.create(
                    [
                        Plain(i)
                        if not re.match(&#34;^\$\d+$&#34;, i)
                        else id_elem_map[int(i[1:])]
                        for i in re.split(r&#34;((?&lt;!\\)\$[0-9]+)&#34;, v)
                        if i
                    ]
                ).asMerged()
                if isinstance(self.arguments[map_with_bar[k]], BoxParameter)
                else (
                    self.arguments[map_with_bar[k]].auto_reverse
                    and not self.arguments[map_with_bar[k]].default
                    or True
                ),
                self.arguments[map_with_bar[k]],
            )
            for k, v in parsed_args
        }
        variables = [
            MessageChain.create(
                [
                    Plain(i) if not re.match(&#34;^\$\d+$&#34;, i) else id_elem_map[int(i[1:])]
                    for i in re.split(r&#34;((?&lt;!\\)\$[0-9]+)&#34;, v)
                    if i
                ]
            ).asMerged()
            for v in variables
        ]
        for param_name, argument_setting in self.arguments.items():
            if param_name not in parsed_args:
                if argument_setting.default is not None:
                    parsed_args[param_name] = (
                        argument_setting.default,
                        argument_setting,
                    )
                else:
                    raise ExecutionStop()

        return (parsed_args, variables)

    def prefix_match(self, target_chain: MessageChain):
        target_chain = target_chain.asMerged()

        chain_frames: List[MessageChain] = target_chain.split(&#34; &#34;, raw_string=True)

        # 前缀匹配
        if len(self.prefixs) &gt; len(chain_frames):
            return
        for index, current_prefix in enumerate(self.prefixs):
            current_frame = chain_frames[index]
            if (
                not current_frame.__root__
                or type(current_frame.__root__[0]) is not Plain
            ):
                return
            if current_frame.__root__[0].text != current_prefix:
                return

        chain_frames = chain_frames[len(self.prefixs) :]
        return MessageChain.create(
            list(itertools.chain(*[i.__root__ + [Plain(&#34; &#34;)] for i in chain_frames]))[
                :-1
            ]
        ).asMerged()

    async def beforeDispatch(self, interface: DispatcherInterface):
        message_chain: MessageChain = (
            await interface.lookup_param(
                &#34;__literature_messagechain__&#34;, MessageChain, None
            )
        ).exclude(Source)
        if set([i.__class__ for i in message_chain.__root__]).intersection(
            BLOCKING_ELEMENTS
        ):
            raise ExecutionStop()
        if self.allow_quote and message_chain.has(Quote):
            # 自动忽略自 Quote 后第一个 At
            message_chain = message_chain[(1, None):]
            if self.skip_one_at_in_quote and message_chain.__root__:
                if message_chain.__root__[0].__class__ is At:
                    message_chain = message_chain[(1, 1):]
        noprefix = self.prefix_match(message_chain)
        if noprefix is None:
            raise ExecutionStop()

        interface.execution_contexts[-1].literature_detect_result = self.parse_message(
            noprefix
        )

    async def catch(self, interface: DispatcherInterface):
        if interface.name == &#34;__literature_messagechain__&#34;:
            return

        result = interface.execution_contexts[-1].literature_detect_result
        if result:
            match_result, variargs = result
            if interface.default == &#34;__literature_variables__&#34;:
                return variargs

            arg_fetch_result = match_result.get(interface.name)
            if arg_fetch_result:

                match_value, raw_argument = arg_fetch_result
                if isinstance(raw_argument, SwitchParameter):
                    return Force(match_value)
                elif interface.annotation is ParamPattern:
                    return raw_argument
                elif match_value is not None:
                    return match_value</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
<li><a title="graia.broadcast.entities.dispatcher.BaseDispatcher" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher">BaseDispatcher</a></li>
</ul>
<h3>Class variables</h3>
<dl>
<dt id="graia.application.message.parser.literature.Literature.allow_quote"><code class="name">var <span class="ident">allow_quote</span> : bool</code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="graia.application.message.parser.literature.Literature.always"><code class="name">var <span class="ident">always</span></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="graia.application.message.parser.literature.Literature.arguments"><code class="name">var <span class="ident">arguments</span> : Dict[str, <a title="graia.application.message.parser.pattern.ParamPattern" href="pattern.html#graia.application.message.parser.pattern.ParamPattern">ParamPattern</a>]</code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="graia.application.message.parser.literature.Literature.prefixs"><code class="name">var <span class="ident">prefixs</span> : Tuple[str]</code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt id="graia.application.message.parser.literature.Literature.skip_one_at_in_quote"><code class="name">var <span class="ident">skip_one_at_in_quote</span> : bool</code></dt>
<dd>
<div class="desc"></div>
</dd>
</dl>
<h3>Methods</h3>
<dl>
<dt id="graia.application.message.parser.literature.Literature.gen_long_map"><code class="name flex">
<span>def <span class="ident">gen_long_map</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def gen_long_map(self):
    result = {}
    for param_name, arg in self.arguments.items():
        for long in arg.longs:
            if long in result:
                raise ValueError(&#34;conflict item&#34;)
            result[long] = param_name
    return result</code></pre>
</details>
</dd>
<dt id="graia.application.message.parser.literature.Literature.gen_long_map_with_bar"><code class="name flex">
<span>def <span class="ident">gen_long_map_with_bar</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def gen_long_map_with_bar(self):
    return {(&#34;--&#34; + k): v for k, v in self.gen_long_map().items()}</code></pre>
</details>
</dd>
<dt id="graia.application.message.parser.literature.Literature.gen_short_map"><code class="name flex">
<span>def <span class="ident">gen_short_map</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def gen_short_map(self):
    result = {}
    for param_name, arg in self.arguments.items():
        if arg.short in result:
            raise ValueError(&#34;conflict item&#34;)
        result[arg.short] = param_name
    return result</code></pre>
</details>
</dd>
<dt id="graia.application.message.parser.literature.Literature.gen_short_map_with_bar"><code class="name flex">
<span>def <span class="ident">gen_short_map_with_bar</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def gen_short_map_with_bar(self):
    return {(&#34;-&#34; + k): v for k, v in self.gen_short_map().items() if k is not None}</code></pre>
</details>
</dd>
<dt id="graia.application.message.parser.literature.Literature.parse_message"><code class="name flex">
<span>def <span class="ident">parse_message</span></span>(<span>self, message_chain: <a title="graia.application.message.chain.MessageChain" href="../chain.html#graia.application.message.chain.MessageChain">MessageChain</a>)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def parse_message(self, message_chain: MessageChain):
    string_result, id_elem_map = self.trans_to_map(message_chain)

    parsed_args, variables = getopt.getopt(
        shlex.split(string_result),
        &#34;&#34;.join(
            [
                arg.short if isinstance(arg, SwitchParameter) else (arg.short + &#34;:&#34;)
                for arg in self.arguments.values()
                if arg.short
            ]
        ),
        [
            long if isinstance(arg, SwitchParameter) else long + &#34;=&#34;
            for arg in self.arguments.values()
            for long in arg.longs
        ],
    )
    map_with_bar = {**self.gen_long_map_with_bar(), **self.gen_short_map_with_bar()}
    parsed_args = {
        map_with_bar[k]: (
            MessageChain.create(
                [
                    Plain(i)
                    if not re.match(&#34;^\$\d+$&#34;, i)
                    else id_elem_map[int(i[1:])]
                    for i in re.split(r&#34;((?&lt;!\\)\$[0-9]+)&#34;, v)
                    if i
                ]
            ).asMerged()
            if isinstance(self.arguments[map_with_bar[k]], BoxParameter)
            else (
                self.arguments[map_with_bar[k]].auto_reverse
                and not self.arguments[map_with_bar[k]].default
                or True
            ),
            self.arguments[map_with_bar[k]],
        )
        for k, v in parsed_args
    }
    variables = [
        MessageChain.create(
            [
                Plain(i) if not re.match(&#34;^\$\d+$&#34;, i) else id_elem_map[int(i[1:])]
                for i in re.split(r&#34;((?&lt;!\\)\$[0-9]+)&#34;, v)
                if i
            ]
        ).asMerged()
        for v in variables
    ]
    for param_name, argument_setting in self.arguments.items():
        if param_name not in parsed_args:
            if argument_setting.default is not None:
                parsed_args[param_name] = (
                    argument_setting.default,
                    argument_setting,
                )
            else:
                raise ExecutionStop()

    return (parsed_args, variables)</code></pre>
</details>
</dd>
<dt id="graia.application.message.parser.literature.Literature.prefix_match"><code class="name flex">
<span>def <span class="ident">prefix_match</span></span>(<span>self, target_chain: <a title="graia.application.message.chain.MessageChain" href="../chain.html#graia.application.message.chain.MessageChain">MessageChain</a>)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def prefix_match(self, target_chain: MessageChain):
    target_chain = target_chain.asMerged()

    chain_frames: List[MessageChain] = target_chain.split(&#34; &#34;, raw_string=True)

    # 前缀匹配
    if len(self.prefixs) &gt; len(chain_frames):
        return
    for index, current_prefix in enumerate(self.prefixs):
        current_frame = chain_frames[index]
        if (
            not current_frame.__root__
            or type(current_frame.__root__[0]) is not Plain
        ):
            return
        if current_frame.__root__[0].text != current_prefix:
            return

    chain_frames = chain_frames[len(self.prefixs) :]
    return MessageChain.create(
        list(itertools.chain(*[i.__root__ + [Plain(&#34; &#34;)] for i in chain_frames]))[
            :-1
        ]
    ).asMerged()</code></pre>
</details>
</dd>
<dt id="graia.application.message.parser.literature.Literature.trans_to_map"><code class="name flex">
<span>def <span class="ident">trans_to_map</span></span>(<span>self, message_chain: <a title="graia.application.message.chain.MessageChain" href="../chain.html#graia.application.message.chain.MessageChain">MessageChain</a>)</span>
</code></dt>
<dd>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def trans_to_map(self, message_chain: MessageChain):
    string_result: List[str] = []
    id_elem_map: Dict[int, Element] = {}

    for elem in message_chain.__root__:
        if isinstance(elem, Plain):
            string_result.append(
                re.sub(
                    r&#34;\$(?P&lt;id&gt;\d+)&#34;,
                    lambda match: f&#39;\\${match.group(&#34;id&#34;)}&#39;,
                    elem.text,
                )
            )
        else:
            index = len(id_elem_map) + 1
            string_result.append(f&#34;${index}&#34;)
            id_elem_map[index] = elem

    return (&#34;&#34;.join(string_result), id_elem_map)</code></pre>
</details>
</dd>
</dl>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="graia.broadcast.entities.dispatcher.BaseDispatcher" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher">BaseDispatcher</a></b></code>:
<ul class="hlist">
<li><code><a title="graia.broadcast.entities.dispatcher.BaseDispatcher.afterDispatch" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher.afterDispatch">afterDispatch</a></code></li>
<li><code><a title="graia.broadcast.entities.dispatcher.BaseDispatcher.afterExecution" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher.afterExecution">afterExecution</a></code></li>
<li><code><a title="graia.broadcast.entities.dispatcher.BaseDispatcher.afterTargetExec" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher.afterTargetExec">afterTargetExec</a></code></li>
<li><code><a title="graia.broadcast.entities.dispatcher.BaseDispatcher.beforeDispatch" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher.beforeDispatch">beforeDispatch</a></code></li>
<li><code><a title="graia.broadcast.entities.dispatcher.BaseDispatcher.beforeExecution" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher.beforeExecution">beforeExecution</a></code></li>
<li><code><a title="graia.broadcast.entities.dispatcher.BaseDispatcher.beforeTargetExec" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher.beforeTargetExec">beforeTargetExec</a></code></li>
<li><code><a title="graia.broadcast.entities.dispatcher.BaseDispatcher.catch" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher.catch">catch</a></code></li>
<li><code><a title="graia.broadcast.entities.dispatcher.BaseDispatcher.mixin" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher.mixin">mixin</a></code></li>
<li><code><a title="graia.broadcast.entities.dispatcher.BaseDispatcher.onActive" href="../../../broadcast/entities/dispatcher.html#graia.broadcast.entities.dispatcher.BaseDispatcher.onActive">onActive</a></code></li>
</ul>
</li>
</ul>
</dd>
</dl>
</section>
</article>
<nav id="sidebar">
<h1>Index</h1>
<div class="toc">
<ul></ul>
</div>
<ul id="index">
<li><h3>Super-module</h3>
<ul>
<li><code><a title="graia.application.message.parser" href="index.html">graia.application.message.parser</a></code></li>
</ul>
</li>
<li><h3><a href="#header-classes">Classes</a></h3>
<ul>
<li>
<h4><code><a title="graia.application.message.parser.literature.Literature" href="#graia.application.message.parser.literature.Literature">Literature</a></code></h4>
<ul class="">
<li><code><a title="graia.application.message.parser.literature.Literature.allow_quote" href="#graia.application.message.parser.literature.Literature.allow_quote">allow_quote</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.always" href="#graia.application.message.parser.literature.Literature.always">always</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.arguments" href="#graia.application.message.parser.literature.Literature.arguments">arguments</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.gen_long_map" href="#graia.application.message.parser.literature.Literature.gen_long_map">gen_long_map</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.gen_long_map_with_bar" href="#graia.application.message.parser.literature.Literature.gen_long_map_with_bar">gen_long_map_with_bar</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.gen_short_map" href="#graia.application.message.parser.literature.Literature.gen_short_map">gen_short_map</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.gen_short_map_with_bar" href="#graia.application.message.parser.literature.Literature.gen_short_map_with_bar">gen_short_map_with_bar</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.parse_message" href="#graia.application.message.parser.literature.Literature.parse_message">parse_message</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.prefix_match" href="#graia.application.message.parser.literature.Literature.prefix_match">prefix_match</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.prefixs" href="#graia.application.message.parser.literature.Literature.prefixs">prefixs</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.skip_one_at_in_quote" href="#graia.application.message.parser.literature.Literature.skip_one_at_in_quote">skip_one_at_in_quote</a></code></li>
<li><code><a title="graia.application.message.parser.literature.Literature.trans_to_map" href="#graia.application.message.parser.literature.Literature.trans_to_map">trans_to_map</a></code></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
</main>
<footer id="footer">
<p>Generated by <a href="https://pdoc3.github.io/pdoc"><cite>pdoc</cite> 0.9.2</a>.</p>
</footer>
</body>
</html>